/*
*STANDARD FOR MODIFYING:
*Date: MM/DD/YYYY
*Modification: "Insert the modification done here"
*Authoring Software for Modification: "Program used to modify"
*
*AUTHOR: Jose Castellano
*
*AUTHORING SOFTWARE: nVidia FX Composer 2.5
*
*DESCRIPTION: This is a simple Blinn Phong Shader
*
*DATE CREATED:10/26/2011
*
*DATE MODIFIED:
*
*MODIFICATION:
*
*AUTHORING SOFTWARE FOR MODIFICATION:
*/


/////////////////////////////////////////////////////////////////////////////
//Untweakable Global Variables
/////////////////////////////////////////////////////////////////////////////

/*World Matrix for Transforming Positions into World Space*/
float4x4 WorldXF		:	World
< 
string UIWidget="None"; 
>;

/*World Matrix for Transforming Vertex Normals into World Space*/
float4x4 WorldITXF		:	WorldInverseTranspose
< 
string UIWidget="None"; 
>;

/*World Matrix for Transforming Positions into clip/view Space*/
float4x4 WVPXF			:	WorldViewProjection
< 
string UIWidget="None"; 
>;

/////////////////////////////////////////////////////////////////////////////
//User Defined Variables
/////////////////////////////////////////////////////////////////////////////

/*Eye or Camera Position*/
float3 EyePosition		:	Position
<
	string Object = "Camera";
	string UIName = "Camera Position";
	string Space = "World Space";
> = {-0.5f, 2.0f, 1.25f};

/*Light's Position*/
float3 Light0Pos		:	Position
<
	string Object = "PointLight0";
	string UIName = "Light 0 Position";
	string Space = "World Space";
> = {-0.5f, 2.0f, 1.25f};

/*Light's Specular Color*/
float3 Light0ColorSpecular	:	Specular
<
    string Object = "Pointlight0";
	string UIName =  "Light 0 Specular";
    string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f};

/*Light's Ambient Color*/
float3 Light0ColorAmbient	:	Ambient 
<
    string Object = "Pointlight0";
	string UIName =  "Light 0 Ambient";
    string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f};

/*Light's Diffuse Color*/
float3 Light0ColorDiffuse	:	Diffuse 
<
    string Object = "Pointlight0";
	string UIName =  "Light 0 Diffuse";
    string UIWidget = "Color";
> = {1.0f, 1.0f, 1.0f};

/*Light's Constant Attenuation*/
float Light0ConstAtten		:	CONSTANTATTENUATION 
<
    string Object = "Pointlight0";
	string UIName =  "Light 0 Attenuation";
> = 1.0f;

/*Light's Linear Attenuation*/
float Light0LinearAtten		:	LINEARATTENUATION 
<
    string Object = "Pointlight0";
	string UIName =  "Light 0 Attenuation";
> = 1.0f;

/*Light's Quadradic Attenuation*/
float Light0QuadAtten		:	QUADRATICATTENUATION 
<
    string Object = "Pointlight0";
	string UIName =  "Light 0 Attenuation";
> = 1.0f;

/*Material Parameters*/
float4 MatAmbientColor		:	Ambient
<
	string UIName = "Material Ambient Color";
	string UIWidget = "Color";
> = {1.3f, 0.9f, 0.15f, 1.0f};

float4 MatDiffuseColor		:	Diffuse
<
	string UIName = "Material Diffuse Color";
	string UIWidget = "Color";
> = {0.05f, 0.05f, 0.6f, 1.0f};

float4 MatSpecularColor		:	Specular
<
	string UIName = "Material Specular Color";
	string UIWidget = "Color";
> = {0.05f, 0.05f, 0.6f, 1.0f};

float SpecularPower
<
	string UIName = "Material Specular Power";
	string UIWidget = "slider";
    float UIMin = 1.0;
    float UIMax = 128.0;
    float UIStep = 1.0;
> = 55.0f;

/*Texture Types and Parameters*/
texture DiffuseTexture		:	DIFFUSE 
<
    string ResourceName = "default_color.dds";
    string UIName =  "Diffuse Texture";
    string ResourceType = "2D";
>;

/*Other Misc.*/
bool hasTexture
<
	string UIName = "Does it Have a Texture?";
	string UIWidget = "Checkbox";
> = true;

/////////////////////////////////////////////////////////////////////////////
//Data Structures
/////////////////////////////////////////////////////////////////////////////

/*Texture Sampler*/
sampler texSamp = sampler_state
{
	/*The texture to be sampled in this sampler*/
	Texture = <DiffuseTexture>;
	
	/*The filter Types*/
	/*MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;*/
	FILTER = MIN_MAG_MIP_LINEAR;
	
	/*Address Modes*/
};

/*Structure for the incoming vertex buffer data*/
struct appdata
{
	float3 Position 	: 	POSITION0;
	float3 Normal		:	NORMAL0;
	float2 Texture		:	TEXCOORD0;
};

/*Structure for the data created in the Vertex Shader to be sent to the Pixel
Shader*/

struct vertexOutput
{
	float4 HPosition 	:	POSITION0;
	float3 WPosition 	:	TEXCOORD0;
	float3 WorldNormal	:	TEXCOORD1;
	float2 Texture		:	TEXCOORD2;
};

/////////////////////////////////////////////////////////////////////////////
//Shaders
/////////////////////////////////////////////////////////////////////////////

/*Vertex Shader*/
vertexOutput std_VS(appdata IN)
{
	/*Create a new Blank Vertex Output*/
	vertexOutput OUT = (vertexOutput)0;
	
	/*Since the Normal was sent in as a float3 make it a float4*/
	float4 No = float4(IN.Normal, 0);
	
	/*Transform the Normal to world space*/
	OUT.WorldNormal = mul(No, WorldITXF).xyz;
	
	/*Make sure that the Normal is normalized*/
	float3 Nn = normalize(OUT.WorldNormal);
	
	/*Since the Position was sent in as a float3 make it a float4*/
	float4 Po = float4(IN.Position, 1);
	
	/*Transform the Position to world space*/
	OUT.WPosition = mul(Po, WorldXF).xyz;
	
	/*Transform and store the Position into clip space*/
	OUT.HPosition = mul(Po, WVPXF);
	
	/*Set the Texture Coordinates*/
	OUT.Texture = IN.Texture;
	
	return OUT;
}

/*Pixel Shader*/
float4 blinn_Phong_PS(vertexOutput IN) : COLOR
{
	/*Create the variable to hold the texture color if one exists*/
	float3 texColor;
	
	/*Run a check and calculate the texture color*/
	if(hasTexture)
	{
		texColor = tex2D(texSamp, IN.Texture).rgb;
	}
	
	/*Make sure that the Normal is normalized*/
	float3 Nn = normalize(IN.WorldNormal);
	
	float3 toEye = normalize(EyePosition - IN.WPosition);
	
	/*Subtract the Position of the object from the Position of the Light
	to get the Light Direction Vector*/
	float3 LightVec = (Light0Pos - IN.WPosition.xyz);
	
	/*Half Vector is used in Blinn-Phong Shading(Rather than calculating
	reflection*/
	float3 H = normalize(LightVec + normalize(toEye));
	
	float T = pow(max(dot(H, IN.WorldNormal), 0.0f), SpecularPower);
	
	/*Determine the diffuse light intensity*/
	float S = max(dot(LightVec, IN.WorldNormal), 0.0f);
	
	/*Compute the Ambient, Diffuse, and Specular Terms Seperately*/
	float3 spec = (float3)0;
	float3 diffuse = (float3)0;
	float3 ambient = (float3)0;
	
	if(hasTexture)
	{
		spec = T * (MatSpecularColor * Light0ColorSpecular).rgb;
		diffuse = S * (MatDiffuseColor * texColor * Light0ColorDiffuse);
		ambient = (MatAmbientColor * texColor * Light0ColorAmbient);
	}
	else
	{
		spec = T * (MatSpecularColor * Light0ColorSpecular).rgb;
		diffuse = S * (MatDiffuseColor * Light0ColorDiffuse);
		ambient = (MatAmbientColor * Light0ColorAmbient);
	}
	
	/*Apply Attenuation Calculations*/
	float d = distance(LightVec, IN.WPosition);
	float A = Light0ConstAtten + Light0LinearAtten * d + 
	Light0QuadAtten * d * d;
	
	/*Sum All of the terms together*/
	float3 result = (ambient + (diffuse + spec)) / A;
	
	/*Since the Pixel Shader is returning a float4 convert the result from 
	float3 to float4 using the DiffuseColor's Alpha for the 4th value*/
	return float4(result, MatDiffuseColor.a);
}

/////////////////////////////////////////////////////////////////////////////
//Techniques along with their passes
/////////////////////////////////////////////////////////////////////////////

technique Blinn_Phong
<
	string Script = "Pass = p0;";
>
{
	pass p0
	<
		string Script = "Draw = geometry;";
	>
	{
		/*Call the Vertex Shader*/
		VertexShader = compile vs_3_0 std_VS();
		
		/*Call the Pixel Shader*/
		PixelShader = compile ps_3_0 blinn_Phong_PS();
		
		/*Manipulate the Rendering States*/
	}
}